import viewbuilder.support.WebViewBuilderExecuter
import dsl.PostDsl

class PostController extends PostDsl {

    def postService
    def tags
    def blogConfig

    def beforeInterceptor = {
        tags = Tag.list()
        blogConfig = BlogConfig.list()[0]
    }

    def defaultAction = 'list'

    def edit = {
        def post = postService.loadPostByUrlTitle(params.id)
        display(editView(given(post)))
    }

    def save = {
        def post = new Post(params)        

        display(editView(given(invalid(post))))
        post = save(valid(post), given(params))
        if(post) {
            println("-- about to redirect to view with id:${post.urlTitle}")
            redirect(action:"view", id:post.urlTitle)
        }

//        sendUser(
//                after(
//                        save(valid(post), given(params))),
//                to("view"))
        post = save(valid(post), given(params))
    }

    def list = {
        def posts = postService.publishedPosts()
        renderViewBuilder(
                viewBuilder:"list",
                model:[posts:posts,
                        tags:tags,
                        blogConfig:blogConfig])
    }

    def postsInProgress = {
        def posts = postService.unpublishedPosts()
        renderViewBuilder(
                viewBuilder:"list",
                model:[posts:posts,
                        tags:tags,
                        blogConfig:blogConfig])
    }

    def listByTag = {
        def tag = Tag.findByName(params.id)
        renderViewBuilder(
                viewBuilder:"list",
                model:[posts:tag.posts,
                        tags:tags,
                        tag:tag,
                        blogConfig:blogConfig])
    }

    def publish = {
        def post = Post.get(params.id)
        post.published = true
        post.save()
        redirect(action:"list")
    }

    def unpublish = {
        def post = Post.get(params.id)
        post.published = false
        post.save()
        redirect(action:"list")
    }

    def suggestTags = {
        flash.possibleTags = params.value
        def tags = []
        params.value?.tokenize().each {token ->
            Tag.findAllByNameLike("%${token}%").each {match ->
                if (!tags.contains(match)) {
                    tags << match
                }
            }
        }
        params.value?.tokenize().each {token ->
            Tag.findAllByName("${token}").each {fullMatch ->
                tags.remove(fullMatch)
            }
        }
        render(view: "suggestTags", model: [suggestedTags: tags])
    }

    def selectSuggestion = {
        println("The suggestion selected was ${params.id}")
        def lastToken
        flash.possibleTags.tokenize().each {
            lastToken = it
        }
        def remainingTags = flash.possibleTags[0..<flash.possibleTags.size() - lastToken.size()]
        render(view: "selectSuggestion", model: [possibleTags: remainingTags <<= params.id])
    }

    def editTags = {
        render(template: "editTags",
                model: [post: Post.get(params.id)])
    }

    def saveTags = {
        def post = postService.loadPost(params.id)
        postService.populateTags(post, params.tagString)
        if (post.save()) {
            render(template: "showTags", model: [post: post])
        } else {
            render("Save failed")
        }
    }

    def showTags = {
        render(template: 'showTags',
                model: [post: Post.get(params.id)])
    }

    def view = {
        renderViewBuilder(
            viewBuilder:"view",
            model: [post: Post.findByUrlTitle(params.id),
                    tags:tags,
                    blogConfig:blogConfig])
    }

    def rss = {
        def posts = postService.publishedPosts()
        renderViewBuilder(
                viewBuilder:"rss",
                contentType: "text/xml",
                model:[posts:posts,
                        blogConfig:blogConfig])
    }

    def renderViewBuilder(args) {

        def executer = new WebViewBuilderExecuter(this.class.classLoader,
                grailsApplication.config.viewComponents.location,
                grailsApplication.config.viewComponents.packageLocation)

        def scriptLocation = getScriptLocation(grailsApplication, args.viewBuilder)
        executer.execute(servletContext, scriptLocation, args.model, request, null)

        def renderArgs = [:]
        renderArgs.text = executer.writer.toString()
        if(args.contentType) {
            renderArgs.contentType = args.contentType
        }
        render(renderArgs)
    }

    def getScriptLocation(grailsApp, viewBuilder) {
        def location = grailsApp.config.viewBuilder.location
        return "${location}/${viewBuilder}PostViewBuilder.groovy"
    }

    def display(args) {
        if(args) {
            render(args)
        }
    }

}
